#include "../include/Bitmap.h"
#include "../include/View.h"
#include "../base.h"

#define  LOG_TAG    "NativeView"

typedef void (*EditTextCallback) ( jstring string,int cur );
static EditTextCallback mOnSure=NULL;
static EditTextCallback mOnCancel=NULL;
static int mScreenWidth = 0;
static int mScreenHeight = 0;
static float mScreenDensity = 0;
static jobject mActivity = NULL;

struct Method_st{
	jmethodID methodID;
	char * methodName;
	char * methodParm;
};
typedef struct Method_st Method;

struct MethodIds_st{
	//public static void setStrokeWidth(float width)
	Method setStrokeWidth;
	//public static void setStroke(boolean stroke)
	Method setStroke;
	//public static void canvasSave()
	Method canvasSave;

	//public static void canvasRestore()
	Method canvasRestore;
	//public static void canvasClipRect(float left,float top,float right,float bottom)
	Method canvasClipRect;
	//public static void canvasRotate(float degrees,float px,float py)
	Method canvasRotate;
	//public static void canvasTranslate(float dx,float dy)
	Method canvasTranslate;
	//public static void canvasScale(float sx, float sy, float px, float py)
	Method canvasScale;

	//public static void drawColor(int color)
	Method drawColor;
	//public static void setColor(int color)
	Method setColor;
	//public static void setTextSize(float size)
	Method setTextSize;
	//public static void drawLine(float startX,float startY,float stopX,float stopY)
	Method drawLine;
	//void drawText(String text,int start,int end,float x,float y)
	Method drawText;

	//public static void drawRect(float left, float top, float right, float bottom)
	Method drawRect;
	//public static void drawRoundRect(float left, float top, float right, float bottom,float rx,float ry)
	Method drawRoundRect;
    //public static void invalidate()
	Method invalidate;
	//public static void postInvalidate()
	Method postInvalidate;
	//public static void invalidateRect(int left,int top,int right,int bottom)
	Method invalidateRect;

	//public static void postInvalidateRect(int left,int top,int right,int bottom)
	Method postInvalidateRect;
	//public static Bitmap decodeBitmapFromAssets(String name)
	Method decodeBitmapFromAssets;
	//public static Bitmap decodeBitmapFromFile(String path)
	Method decodeBitmapFromFile;
	//public static Bitmap createBitmap(int width,int height)
	Method createBitmap;
	
	Method createBitmapRgb565;

	//public static boolean saveBitmapToFile(Bitmap bitmap,String path,int type,int quality)
	Method saveBitmapToFile;
	//public static void drawBitmap(Bitmap bitmap,int fromLeft,int fromTop,int fromRight,int fromBottom,float toLeft,float toTop,float toRight,float toBottom)
	Method drawBitmap;

	//public float measureText(String text,int start,int end)
	Method measureText;
	//public static void finish()
	Method finish;
	//public boolean requestEditText(String title,String string,int cur)
	Method requestEditText;
	//public static void showToast(String string,int time)
	Method showToast;
	//public static long currentTimeMillis();
	Method currentTimeMillis;

	//public static long nanoTime();
	Method nanoTime;
	//public static byte []readAllFromAssets(String name)
	Method readAllFromAssets;
	//public static MediaPlayer createMediaPlayer()
	Method createMediaPlayer;
	//public static boolean mediaPlayerSetSourceFromAssert(MediaPlayer mediaPlayer,String path)
	Method mediaPlayerSetSourceFromAssert;
	//public static boolean mediaPlayerSetSourceFromPath(MediaPlayer mediaPlayer,String path)
	Method mediaPlayerSetSourceFromPath;

	//public static boolean mediaPlayerPrepare(MediaPlayer mediaPlayer)
	Method mediaPlayerPrepare;
	//public static boolean mediaPlayerStart(MediaPlayer mediaPlayer)
	Method mediaPlayerStart;
	//public static boolean mediaPlayerStop(MediaPlayer mediaPlayer)
	Method mediaPlayerStop;
	//public static boolean mediaPlayerReset(MediaPlayer mediaPlayer)
	Method mediaPlayerReset;
	//public static boolean mediaPlayerRlease(MediaPlayer mediaPlayer)
	Method mediaPlayerRlease;

	//public static boolean mediaPlayerPause(MediaPlayer mediaPlayer)
	Method mediaPlayerPause;
	//public static boolean mediaPlayerSetLooping(MediaPlayer mediaPlayer,boolean looping)
	Method mediaPlayerSetLooping;
	//public static boolean mediaPlayerIsLooping(MediaPlayer mediaPlayer)
	Method mediaPlayerIsLooping;
	//public static boolean mediaPlayerIsPlaying(MediaPlayer mediaPlayer)
	Method mediaPlayerIsPlaying;
	//public static boolean mediaPlayerSetVolume(MediaPlayer mediaPlayer,float leftVolume,float rightVolume)
	Method mediaPlayerSetVolume;

	//public static boolean mediaPlayerSeekTo(MediaPlayer mediaPlayer,int msec)
	Method mediaPlayerSeekTo;
	//public static int mediaPlayerGetDuration(MediaPlayer mediaPlayer)
	Method mediaPlayerGetDuration;
	//public static int mediaPlayerGetCurrentPosition(MediaPlayer mediaPlayer)
	Method mediaPlayerGetCurrentPosition;
	//public static float getDensity()
	Method getDensity;
} mMethods =
{
		{NULL,"setStrokeWidth"	,"(F)V"},
		{NULL,"setStroke"	,"(Z)V"},
		{NULL,"canvasSave"	,"()V"},

		{NULL,"canvasRestore"	,"()V"},
		{NULL,"canvasClipRect"	,"(FFFF)V"},
		{NULL,"canvasRotate"	,"(FFF)V"},
		{NULL,"canvasTranslate"	,"(FF)V"},
		{NULL,"canvasScale"	,"(FFFF)V"},

		{NULL,"drawColor"	,"(I)V"},
		{NULL,"setColor"	,"(I)V"},
		{NULL,"setTextSize"	,"(F)V"},
		{NULL,"drawLine"	,"(FFFF)V"},
		{NULL,"drawText"	,"(Ljava/lang/String;IIFF)V"},

		{NULL,"drawRect"	,"(FFFF)V"},
		{NULL,"drawRoundRect"	,"(FFFFFF)V"},
		{NULL,"invalidate"		,"()V"},
		{NULL,"postInvalidate"	,"()V"},
		{NULL,"invalidateRect"	,"(IIII)V"},

		{NULL,"postInvalidateRect"	,"(IIII)V"},
		{NULL,"decodeBitmapFromAssets"	,"(Ljava/lang/String;)Landroid/graphics/Bitmap;"},
		{NULL,"decodeBitmapFromFile"	,"(Ljava/lang/String;)Landroid/graphics/Bitmap;"},
		{NULL,"createBitmap"	,"(II)Landroid/graphics/Bitmap;"},
		{NULL,"createBitmapRgb565"	,"(II)Landroid/graphics/Bitmap;"},
		{NULL,"saveBitmapToFile"	,"(Landroid/graphics/Bitmap;Ljava/lang/String;II)Z"},
		{NULL,"drawBitmap"		,"(Landroid/graphics/Bitmap;IIIIFFFF)V"},

		{NULL,"measureText"		,"(Ljava/lang/String;II)F"},
		{NULL,"finish"			,"()V"},
		{NULL,"requestEditText"	,"(Ljava/lang/String;Ljava/lang/String;I)Z"},
		{NULL,"showToast"		,"(Ljava/lang/String;I)V"},
		{NULL,"currentTimeMillis"	,"()J"},

		{NULL,"nanoTime"		,"()J"},
		{NULL,"readAllFromAssets"		,"(Ljava/lang/String;)[B"},
		{NULL,"createMediaPlayer"		,"()Landroid/media/MediaPlayer;"},
		{NULL,"mediaPlayerSetSourceFromAssert"		,"(Landroid/media/MediaPlayer;Ljava/lang/String;)Z"},
		{NULL,"mediaPlayerSetSourceFromPath"		,"(Landroid/media/MediaPlayer;Ljava/lang/String;)Z"},

		{NULL,"mediaPlayerPrepare"		,"(Landroid/media/MediaPlayer;)Z"},
		{NULL,"mediaPlayerStart"		,"(Landroid/media/MediaPlayer;)Z"},
		{NULL,"mediaPlayerStop"			,"(Landroid/media/MediaPlayer;)Z"},
		{NULL,"mediaPlayerReset"		,"(Landroid/media/MediaPlayer;)Z"},
		{NULL,"mediaPlayerRlease"		,"(Landroid/media/MediaPlayer;)Z"},

		{NULL,"mediaPlayerPause"		,"(Landroid/media/MediaPlayer;)Z"},
		{NULL,"mediaPlayerSetLooping"		,"(Landroid/media/MediaPlayer;Z)Z"},
		{NULL,"mediaPlayerIsLooping"		,"(Landroid/media/MediaPlayer;)Z"},
		{NULL,"mediaPlayerIsPlaying"		,"(Landroid/media/MediaPlayer;)Z"},
		{NULL,"mediaPlayerSetVolume"		,"(Landroid/media/MediaPlayer;FF)Z"},

		{NULL,"mediaPlayerSeekTo"			,"(Landroid/media/MediaPlayer;I)Z"},
		{NULL,"mediaPlayerGetDuration"		,"(Landroid/media/MediaPlayer;)I"},
		{NULL,"mediaPlayerGetCurrentPosition"		,"(Landroid/media/MediaPlayer;)I"},
		{NULL,"getDensity"		,"()F"},
};

#include <pthread.h>
static pthread_key_t mThreadKey;
JavaVM* mJavaVM;
jclass mClazz;

JNIEnv* Android_JNI_GetEnv(void);
static void Android_JNI_ThreadDestroyed(void* value);
static int Android_JNI_SetupThread(void);

/* Library init */
JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM* vm, void* reserved)
{
    JNIEnv *env;
    mJavaVM = vm;
    LOG_INIT();
	_initTimer();
    LOGI("JNI_OnLoad called");
    if ((*mJavaVM)->GetEnv(mJavaVM, (void**) &env, JNI_VERSION_1_4) != JNI_OK) {
        LOGE("Failed to get the environment using GetEnv()");
        return -1;
    }
    /*
     * Create mThreadKey so we can keep track of the JNIEnv assigned to each thread
     * Refer to http://developer.android.com/guide/practices/design/jni.html for the rationale behind this
     */
    if (pthread_key_create(&mThreadKey, Android_JNI_ThreadDestroyed) != 0) {
        LOGE("Error initializing pthread key");
    }
    Android_JNI_SetupThread();
    return JNI_VERSION_1_4;
}

static int Android_JNI_SetupThread(void)
{
    Android_JNI_GetEnv();
    return 1;
}

static void Android_JNI_ThreadDestroyed(void* value)
{
    /* The thread is being destroyed, detach it from the Java VM and set the mThreadKey value to NULL as required */
    JNIEnv *env = (JNIEnv*) value;
    if (env != NULL) {
        (*mJavaVM)->DetachCurrentThread(mJavaVM);
        pthread_setspecific(mThreadKey, NULL);
    }
}


JNIEnv* Android_JNI_GetEnv(void)
{
    JNIEnv *env;
    int status = (*mJavaVM)->AttachCurrentThread(mJavaVM, &env, NULL);
    if(status < 0) {
        LOGE("failed to attach current thread");
        return 0;
    }
    pthread_setspecific(mThreadKey, (void*) env);
    return env;
}

extern void onCreate();
static float getDensity();
void Java_person_wangchen11_nativeview_NativeInterface_init
( JNIEnv* env,jclass clazz,jobject activity)
{
	mActivity = ((*env)->NewGlobalRef(env, activity));
	int i;
	Method *methods=(Method *)&mMethods;
	int methodsSize=sizeof(mMethods)/sizeof(Method);
	mClazz=((*env)->NewGlobalRef(env, clazz));
	for(i=0;i<methodsSize;i++)
	{
		methods[i].methodID=(*env)->GetStaticMethodID(env,clazz,methods[i].methodName,methods[i].methodParm);
	}
	mScreenDensity = getDensity();
	onCreate();
}

#define MAX_POINTER_NUMBER 10
static float mPointersX[MAX_POINTER_NUMBER];
static float mPointersY[MAX_POINTER_NUMBER];
static int  mPointersID[MAX_POINTER_NUMBER];

extern void onTouchEvent(int action,float x,float y,int index,int count,float pointersX[],float pointersY[],int pointersId[]);
jboolean Java_person_wangchen11_nativeview_NativeInterface_touchEvent
( JNIEnv* env,jclass clazz,jint action,jfloat x,jfloat y,jint index,jint count
		,jfloatArray pointersX,jfloatArray pointersY,jintArray pointersId)
{
	(*env)->GetFloatArrayRegion(env,pointersX,0,count,mPointersX);
	(*env)->GetFloatArrayRegion(env,pointersY,0,count,mPointersY);
	(*env)->GetIntArrayRegion(env,pointersId,0,count,mPointersID);
	onTouchEvent(action,x,y,index,count,mPointersX,mPointersY,mPointersID);
	return 1;
}

extern void onDraw(int left,int top,int right,int bottom,jobject canvas);
void Java_person_wangchen11_nativeview_NativeInterface_draw
( JNIEnv* env,jclass clazz,jint left,jint top,jint right,jint bottom,jobject canvas)
{
	onDraw(left,top,right,bottom,canvas);
}

extern void onSizeChange(int w,int h,int oldw,int oldh,float density);
void Java_person_wangchen11_nativeview_NativeInterface_sizeChange
( JNIEnv* env,jclass clazz,jint w,jint h,jint oldw,jint oldh,jfloat density)
{
	mScreenWidth = w;
	mScreenHeight = h;
	mScreenDensity = density;
	onSizeChange(w,h,oldw,oldh,density);
}

extern void onDestroy();
void Java_person_wangchen11_nativeview_NativeInterface_destroy
( JNIEnv* env,jclass clazz)
{
	onDestroy();
	if(mActivity!=NULL)
	{
		(*env)->DeleteGlobalRef(env,mActivity);
	}
}

extern int onBackPressed();
jboolean Java_person_wangchen11_nativeview_NativeInterface_backPressed
( JNIEnv* env,jclass clazz)
{
	return onBackPressed();
}

void Java_person_wangchen11_nativeview_NativeInterface_onEditTextCancel
( JNIEnv* env,jclass clazz,jstring string ,jint cur)
{
	if(mOnCancel!=NULL)
	{
		string = (*env)->NewGlobalRef(env,string);
		mOnCancel(string ,cur);
	}
	mOnCancel=NULL;
	mOnSure=NULL;
}

void Java_person_wangchen11_nativeview_NativeInterface_onEditTextSure
( JNIEnv* env,jclass clazz,jstring string ,jint cur)
{
	if(mOnSure!=NULL)
	{
		string = (*env)->NewGlobalRef(env,string);
		mOnSure(string ,cur);
	}
	mOnCancel=NULL;
	mOnSure=NULL;
}

void onLoopCall();
void Java_person_wangchen11_nativeview_NativeInterface_onLoopCall
( JNIEnv* env,jclass clazz)
{
	_loopCallTimer();
	onLoopCall();
}

void onPause();
void Java_person_wangchen11_nativeview_NativeInterface_onPause
( JNIEnv* env,jclass clazz)
{
	onPause();
}

void onResume();
void Java_person_wangchen11_nativeview_NativeInterface_onResume
( JNIEnv* env,jclass clazz)
{
	onResume();
}

int  getScreenWidth()
{
	return mScreenWidth;
}

int  getScreenHeight()
{
	return mScreenHeight;
}

float getScreenDensity()
{
	return mScreenDensity;
}

void setStrokeWidth(float width)
{
	JNIEnv* env = Android_JNI_GetEnv();
	(*env)->CallStaticVoidMethod(env,mClazz,mMethods.setStrokeWidth.methodID,width);
}

void setStroke(jboolean stroke)
{
	JNIEnv* env = Android_JNI_GetEnv();
	(*env)->CallStaticVoidMethod(env,mClazz,mMethods.setStroke.methodID,stroke);
}


void canvasSave()
{
	JNIEnv* env = Android_JNI_GetEnv();
	(*env)->CallStaticVoidMethod(env,mClazz,mMethods.canvasSave.methodID);
}

void canvasRestore()
{
	JNIEnv* env = Android_JNI_GetEnv();
	(*env)->CallStaticVoidMethod(env,mClazz,mMethods.canvasRestore.methodID);
}

void canvasClipRect(float left,float top,float right,float bottom)
{
	JNIEnv* env = Android_JNI_GetEnv();
	(*env)->CallStaticVoidMethod(env,mClazz,mMethods.canvasClipRect.methodID,left,top,right,bottom);
}

void canvasRotate(float degrees,float px,float py)
{
	JNIEnv* env = Android_JNI_GetEnv();
	(*env)->CallStaticVoidMethod(env,mClazz,mMethods.canvasRotate.methodID,degrees,px,py);
}

void canvasTranslate(float dx,float dy)
{
	JNIEnv* env = Android_JNI_GetEnv();
	(*env)->CallStaticVoidMethod(env,mClazz,mMethods.canvasTranslate.methodID,dx,dy);
}

void canvasScale(float sx,float sy,float px,float py)
{
	JNIEnv* env = Android_JNI_GetEnv();
	(*env)->CallStaticVoidMethod(env,mClazz,mMethods.canvasScale.methodID,sx,sy,px,py);
}

void drawColor(int color)
{
	JNIEnv* env = Android_JNI_GetEnv();
	(*env)->CallStaticVoidMethod(env,mClazz,mMethods.drawColor.methodID,color);
}

void setColor(int color)
{
	JNIEnv* env = Android_JNI_GetEnv();
	(*env)->CallStaticVoidMethod(env,mClazz,mMethods.setColor.methodID,color);
}

void setTextSize(float size)
{
	JNIEnv* env = Android_JNI_GetEnv();
	(*env)->CallStaticVoidMethod(env,mClazz,mMethods.setTextSize.methodID,size);
}

void drawLine( float startX,float startY,float stopX,float stopY)
{
	JNIEnv* env = Android_JNI_GetEnv();
	(*env)->CallStaticVoidMethod(env,mClazz,mMethods.drawLine.methodID,startX,startY,stopX,stopY);
}

jstring createJString(const char* text)
{
	JNIEnv* env = Android_JNI_GetEnv();
	jstring string=(*env)->NewStringUTF(env,text);
	return (*env)->NewGlobalRef(env,string);
}

void deleteJString(jstring string)
{
	JNIEnv* env = Android_JNI_GetEnv();
	(*env)->DeleteGlobalRef(env,string);
}

int lengthOfJString(jstring string)
{
	JNIEnv* env = Android_JNI_GetEnv();
	return (*env)->GetStringLength(env,string);
}


char * getJStringChars(jstring string)
{
	JNIEnv* env = Android_JNI_GetEnv();
	char *ret=NULL;
	const char *chars=(*env)->GetStringUTFChars(env,string,NULL);
	ret = (char *)malloc(strlen(chars)+2);
	strcpy(ret,chars);
	(*env)->ReleaseStringUTFChars(env,string,chars);
	return ret;
}

void drawText(const char* text,float x,float y)
{
	JNIEnv* env = Android_JNI_GetEnv();
	jstring string=createJString(text);
	int len=lengthOfJString(string);
	(*env)->CallStaticVoidMethod(env,mClazz,mMethods.drawText.methodID,string,0,len,x,y);
	deleteJString(string);
}

void drawString(jstring string,float x,float y)
{
	JNIEnv* env = Android_JNI_GetEnv();
	int len=lengthOfJString(string);
	(*env)->CallStaticVoidMethod(env,mClazz,mMethods.drawText.methodID,string,0,len,x,y);
}

void drawRect(float left, float top, float right, float bottom)
{
	JNIEnv* env = Android_JNI_GetEnv();
	(*env)->CallStaticVoidMethod(env,mClazz,mMethods.drawRect.methodID,left,top,right,bottom);
}

void drawRoundRect(float left, float top, float right, float bottom,float rx,float ry)
{
	JNIEnv* env = Android_JNI_GetEnv();
	(*env)->CallStaticVoidMethod(env,mClazz,mMethods.drawRoundRect.methodID,left,top,right,bottom,rx,ry);
}

void invalidate()
{
	JNIEnv* env = Android_JNI_GetEnv();
	(*env)->CallStaticVoidMethod(env,mClazz,mMethods.invalidate.methodID);
}

void postInvalidate()
{
	JNIEnv* env = Android_JNI_GetEnv();
	(*env)->CallStaticVoidMethod(env,mClazz,mMethods.postInvalidate.methodID);
}
void invalidateRect(int left,int top,int right,int bottom)
{
	JNIEnv* env = Android_JNI_GetEnv();
	(*env)->CallStaticVoidMethod(env,mClazz,mMethods.invalidateRect.methodID,left,top,right,bottom);
}
void postInvalidateRect(int left,int top,int right,int bottom)
{
	JNIEnv* env = Android_JNI_GetEnv();
	(*env)->CallStaticVoidMethod(env,mClazz,mMethods.postInvalidateRect.methodID,left,top,right,bottom);
}

Bitmap decodeBitmapFromAssets(const char * name)
{
	JNIEnv* env = Android_JNI_GetEnv();
	jstring string=(*env)->NewStringUTF(env,name);
	Bitmap obj= (*env)->CallStaticObjectMethod(env,mClazz,mMethods.decodeBitmapFromAssets.methodID,string);
	(*env)->DeleteLocalRef(env,string);
	return (*env)->NewGlobalRef(env,obj);
}

Bitmap decodeBitmapFromFile(const char * path)
{
	JNIEnv* env = Android_JNI_GetEnv();
	jstring string=(*env)->NewStringUTF(env,path);
	Bitmap obj= (*env)->CallStaticObjectMethod(env,mClazz,mMethods.decodeBitmapFromFile.methodID);
	(*env)->DeleteLocalRef(env,string);
	return (*env)->NewGlobalRef(env,obj);
}

Bitmap createBitmap(int width,int height)
{
	JNIEnv* env = Android_JNI_GetEnv();
	jobject obj= (*env)->CallStaticObjectMethod(env,mClazz,mMethods.createBitmap.methodID,width,height);
	return (*env)->NewGlobalRef(env,obj);
}

Bitmap createBitmapRgb565(int width,int height)
{
	JNIEnv* env = Android_JNI_GetEnv();
	jobject obj= (*env)->CallStaticObjectMethod(env,mClazz,mMethods.createBitmapRgb565.methodID,width,height);
	return (*env)->NewGlobalRef(env,obj);
}

jboolean saveBitmapToFile(Bitmap bitmap,const char *path,int format,int quality){
	JNIEnv* env = Android_JNI_GetEnv();
	jstring str = createJString(path);
	jboolean ret = (*env)->CallStaticBooleanMethod(env,mClazz,mMethods.saveBitmapToFile.methodID,bitmap,str,format,quality);
	deleteJString(str);
	return ret;
}

void deleteBitmap(Bitmap bitmap)
{
	JNIEnv* env = Android_JNI_GetEnv();
	(*env)->DeleteGlobalRef(env,bitmap);
}

void getBitmapInfo(Bitmap bitmap,AndroidBitmapInfo *bitmapInfo)
{
	JNIEnv* env = Android_JNI_GetEnv();
	AndroidBitmap_getInfo(env,bitmap,bitmapInfo);
}

void drawBitmap(Bitmap bitmap
		,int fromLeft,int fromTop,int fromRight,int fromBottom
		,float toLeft,float toTop,float toRight,float toBottom)
{
	JNIEnv* env = Android_JNI_GetEnv();
	(*env)->CallStaticVoidMethod(env,mClazz,mMethods.drawBitmap.methodID,bitmap
			,fromLeft,fromTop,fromRight,fromBottom
			,toLeft,toTop,toRight,toBottom);
}

float measureText(jstring string)
{
	return measureTextEx(string,0,lengthOfJString(string));
}

float measureTextEx(jstring string,int start,int end)
{
	JNIEnv* env = Android_JNI_GetEnv();
	return (*env)->CallStaticFloatMethod(env,mClazz,mMethods.measureText.methodID,string,start,end);
}

void finish()
{
	JNIEnv* env = Android_JNI_GetEnv();
	(*env)->CallStaticVoidMethod(env,mClazz,mMethods.finish.methodID);
}


int requestEditText(jstring title,jstring string,int cur,EditTextCallback onSure,EditTextCallback onCancel)
{
	JNIEnv* env = Android_JNI_GetEnv();
	jboolean ret=(*env)->CallStaticBooleanMethod(env,mClazz,mMethods.requestEditText.methodID,title,string,cur);
	if(ret == 0)//return false
	{
		return ret;
	}
	mOnSure=onSure;
	mOnCancel=onCancel;
	return ret;
}

void showToast(jstring string,int time)
{
	JNIEnv* env = Android_JNI_GetEnv();
	(*env)->CallStaticVoidMethod(env,mClazz,mMethods.showToast.methodID,string,time);
}

void showToastText(const char *text,int time)
{
	jstring string=createJString(text);
	showToast(string,time);
	deleteJString(string);
}

long long currentTimeMillis()
{
	JNIEnv* env = Android_JNI_GetEnv();
	return (*env)->CallStaticLongMethod(env,mClazz,mMethods.currentTimeMillis.methodID);
}

long long nanoTime()
{
	JNIEnv* env = Android_JNI_GetEnv();
	return (*env)->CallStaticLongMethod(env,mClazz,mMethods.nanoTime.methodID);
}

void *readAllFromAssets(const char *name,int *outLength)
{
	JNIEnv* env = Android_JNI_GetEnv();
	jstring string=createJString(name);
	jarray array=(*env)->CallStaticObjectMethod(env,mClazz,mMethods.readAllFromAssets.methodID,string);
	deleteJString(string);
	if(array==NULL)
	{
		*outLength=-1;
		return NULL;
	}
	*outLength=(*env)->GetArrayLength(env,array);
	if(*outLength<0)
	{
		*outLength=-1;
		return NULL;
	}
	void *retData=(void *)malloc(*outLength+2);
	if(retData==NULL)
	{
		LOGE("readAllFromAssets:out of memory!");
		*outLength=-1;
		return NULL;
	}
	memset(retData,0,*outLength+2);
	(*env)->GetByteArrayRegion(env,array,0,*outLength,(jbyte*)retData);
	return retData;
}


jobject createMediaPlayer()
{
	JNIEnv* env = Android_JNI_GetEnv();
	jobject mediaPlayer= (*env)->CallStaticObjectMethod(env,mClazz,mMethods.createMediaPlayer.methodID);
	return (*env)->NewGlobalRef(env,mediaPlayer);
}

jboolean deleteMediaPlayer(jobject mediaPlayer)
{
	JNIEnv* env = Android_JNI_GetEnv();
	jboolean ret = (*env)->CallStaticBooleanMethod(env,mClazz,mMethods.mediaPlayerRlease.methodID,mediaPlayer);
	(*env)->DeleteGlobalRef(env,mediaPlayer);
	return ret;
}

jboolean mediaPlayerSetSourceFromAssert(jobject mediaPlayer,const char *path)
{
	JNIEnv* env = Android_JNI_GetEnv();
	jstring string = createJString(path);
	jboolean ret = (*env)->CallStaticBooleanMethod(env,mClazz,mMethods.mediaPlayerSetSourceFromAssert.methodID,mediaPlayer,string);
	deleteJString(string);
	return ret;
}

jboolean mediaPlayerSetSourceFromPath(jobject mediaPlayer,const char *path)
{
	JNIEnv* env = Android_JNI_GetEnv();
	jstring string = createJString(path);
	jboolean ret = (*env)->CallStaticBooleanMethod(env,mClazz,mMethods.mediaPlayerSetSourceFromPath.methodID,mediaPlayer,string);
	deleteJString(string);
	return ret;
}

jboolean mediaPlayerPrepare(jobject mediaPlayer)
{
	JNIEnv* env = Android_JNI_GetEnv();
	jboolean ret = (*env)->CallStaticBooleanMethod(env,mClazz,mMethods.mediaPlayerPrepare.methodID,mediaPlayer);
	return ret;
}

jboolean mediaPlayerStart(jobject mediaPlayer)
{
	JNIEnv* env = Android_JNI_GetEnv();
	jboolean ret = (*env)->CallStaticBooleanMethod(env,mClazz,mMethods.mediaPlayerStart.methodID,mediaPlayer);
	return ret;
}

jboolean mediaPlayerStop(jobject mediaPlayer)
{
	JNIEnv* env = Android_JNI_GetEnv();
	jboolean ret = (*env)->CallStaticBooleanMethod(env,mClazz,mMethods.mediaPlayerStop.methodID,mediaPlayer);
	return ret;
}

jboolean mediaPlayerReset(jobject mediaPlayer)
{
	JNIEnv* env = Android_JNI_GetEnv();
	jboolean ret = (*env)->CallStaticBooleanMethod(env,mClazz,mMethods.mediaPlayerReset.methodID,mediaPlayer);
	return ret;
}

jboolean mediaPlayerPause(jobject mediaPlayer)
{
	JNIEnv* env = Android_JNI_GetEnv();
	jboolean ret = (*env)->CallStaticBooleanMethod(env,mClazz,mMethods.mediaPlayerPause.methodID,mediaPlayer);
	return ret;
}

jboolean mediaPlayerSetLooping(jobject mediaPlayer,jboolean looping)
{
	JNIEnv* env = Android_JNI_GetEnv();
	jboolean ret = (*env)->CallStaticBooleanMethod(env,mClazz,mMethods.mediaPlayerSetLooping.methodID,mediaPlayer,looping);
	return ret;
}

jboolean mediaPlayerIsLooping(jobject mediaPlayer)
{
	JNIEnv* env = Android_JNI_GetEnv();
	jboolean ret = (*env)->CallStaticBooleanMethod(env,mClazz,mMethods.mediaPlayerIsLooping.methodID,mediaPlayer);
	return ret;
}

jboolean mediaPlayerIsPlaying(jobject mediaPlayer)
{
	JNIEnv* env = Android_JNI_GetEnv();
	jboolean ret = (*env)->CallStaticBooleanMethod(env,mClazz,mMethods.mediaPlayerIsPlaying.methodID,mediaPlayer);
	return ret;
}

jboolean mediaPlayerSetVolume(jobject mediaPlayer,float leftVolume,float rightVolume)
{
	JNIEnv* env = Android_JNI_GetEnv();
	jboolean ret = (*env)->CallStaticBooleanMethod(env,mClazz,mMethods.mediaPlayerSetVolume.methodID,mediaPlayer,leftVolume,rightVolume);
	return ret;
}

jboolean mediaPlayerSeekTo(jobject mediaPlayer,int ms)
{
	JNIEnv* env = Android_JNI_GetEnv();
	jboolean ret = (*env)->CallStaticBooleanMethod(env,mClazz,mMethods.mediaPlayerSeekTo.methodID,mediaPlayer,ms);
	return ret;
}

int mediaPlayerGetDuration(jobject mediaPlayer)
{
	JNIEnv* env = Android_JNI_GetEnv();
	int ret = (*env)->CallStaticIntMethod(env,mClazz,mMethods.mediaPlayerGetDuration.methodID,mediaPlayer);
	return ret;
}

int mediaPlayerGetCurrentPosition(jobject mediaPlayer)
{
	JNIEnv* env = Android_JNI_GetEnv();
	int ret = (*env)->CallStaticIntMethod(env,mClazz,mMethods.mediaPlayerGetCurrentPosition.methodID,mediaPlayer);
	return ret;
}

static float getDensity()
{
	JNIEnv* env = Android_JNI_GetEnv();
	float ret = (*env)->CallStaticFloatMethod(env,mClazz,mMethods.getDensity.methodID);
	return ret;
}

static jclass getClass(JNIEnv* env,const char * className)
{
	return (*env)->FindClass(env,className);
}

jobject getActivity()
{
	return mActivity;
}

void  setContentView(View view)
{
	JNIEnv* env = Android_JNI_GetEnv();
	jclass clazz = getClass(env,"android/app/Activity");
	static jmethodID methoID = NULL;
	if(methoID==NULL)
		methoID = (*env)->GetMethodID(env,clazz,"setContentView","(Landroid/view/View;)V");
	(*env)->DeleteLocalRef(env,clazz);
	(*env)->CallVoidMethod(env,mActivity,methoID,view);
}
